package cn.jbolt.ai.core.chain.node.flow.ifcondition;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.jbolt.ai.core.chain.ChainContext;
import cn.jbolt.ai.core.chain.node.base.AppConfigConstant;
import cn.jbolt.ai.core.chain.node.base.BaseNode;
import cn.jbolt.ai.core.chain.node.provider.BooleanNodeProvider;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class IfConditionNodeProvider extends BaseNode implements BooleanNodeProvider {
    // 运算符标签到值的映射
    private static final Set<String> OPERATOR_MAP = new HashSet<>();
    // 初始化运算符映射
    static {
        // 数值运算符
        OPERATOR_MAP.add("==");

        OPERATOR_MAP.add("!=");

        OPERATOR_MAP.add(">");

        OPERATOR_MAP.add("<");

        OPERATOR_MAP.add(">=");

        OPERATOR_MAP.add("<=");

        // 字符串运算符
        OPERATOR_MAP.add("contains");

        OPERATOR_MAP.add("notcontains");

        OPERATOR_MAP.add("startsWith");

        OPERATOR_MAP.add("endsWith");
    }
    @Override
    public Boolean provide(JsonNode config, ChainContext context) {

        IfNodeConfig ifConfig = IfNodeConfig.from(config.get(AppConfigConstant.CONFIGY_TYPE_IF));

        if (ifConfig == null) {
            throw new RuntimeException("未配置If节点");
        }

        ArrayNode conditions = ifConfig.getFristGroupConditions();
        if (conditions == null || conditions.isEmpty()) {
            throw new RuntimeException("未设置If节点条件");
        }
        Object[] args = new Object[conditions.size() * 2 + 1];
        args[0] = true;
        for (int i = 0; i < conditions.size(); i++) {
            JsonNode condition = conditions.get(i);
            args[i * 2 + 1] = condition.get("link").asText();
            if (condition.has("inputField") == false) {
                throw new RuntimeException("未设置输入字段");
            }
            if (condition.has("operator") == false) {
                throw new RuntimeException("未设置运算符");
            }
            if (condition.has("compareValue") == false) {
                throw new RuntimeException("未设置比较值");
            }
            String inputValue = valueToString(context.getAttr(condition.get("inputField").asText()));

            if (inputValue == null) {
                args[i * 2 + 2] = false;
            }else {
                args[i * 2 + 2] = compare(inputValue, replaceArgs(condition.get("compareValue").asText(), context.getArgs()), condition.get("operator").asText());
            }

        }

        boolean result = evaluateConditions(args);
        if (ifConfig.getOutputField() != null) {
            context.setAttr(ifConfig.getOutputField(), result);
        }
        return result;

    }


    public static void main(String[] args) {
        System.out.println(evaluateConditions(true, "and", false));
    }
    /**
     * Evaluates a boolean expression with AND and OR operators respecting operator precedence.
     * AND has higher precedence than OR.
     *
     * @param args Alternating Boolean values and String operators ("and"/"or")
     * @return The final boolean result
     */
    public static boolean evaluateConditions(Object... args) {
        // Validate input
        if (args.length == 0) {
            throw new IllegalArgumentException("No arguments provided");
        }

        if (args.length % 2 == 0) {
            throw new IllegalArgumentException("Expected odd number of arguments");
        }

        // Create a list to hold our expression elements
        List<Object> expr = new ArrayList<>();

        // Validate and add all arguments
        for (int i = 0; i < args.length; i++) {
            if (i % 2 == 0) {  // Should be a boolean value
                if (!(args[i] instanceof Boolean)) {
                    throw new IllegalArgumentException("Expected boolean at position " + i);
                }
            } else {  // Should be an operator
                if (!(args[i] instanceof String)) {
                    throw new IllegalArgumentException("Expected operator at position " + i);
                }
                String op = ((String) args[i]).toLowerCase();
                if (!op.equals("and") && !op.equals("or")) {
                    throw new IllegalArgumentException("Unsupported operator: " + op);
                }
            }
            expr.add(args[i]);
        }

        // First pass: process all AND operations (higher precedence)
        int i = 1;
        while (i < expr.size()) {
            if (expr.get(i) instanceof String && ((String) expr.get(i)).equals("and")) {
                boolean left = (Boolean) expr.get(i - 1);
                boolean right = (Boolean) expr.get(i + 1);
                boolean result = left && right;

                // Replace the three elements with the result
                expr.set(i - 1, result);
                expr.remove(i);    // Remove operator
                expr.remove(i);    // Remove right operand
            } else {
                i += 2;  // Skip to next operator
            }
        }

        // Second pass: process all OR operations
        boolean result = (Boolean) expr.get(0);
        for (i = 1; i < expr.size(); i += 2) {
            boolean right = (Boolean) expr.get(i + 1);
            result = result || right;
        }


        return result;
    }

    /**
     * 根据给定的运算符比较两个字符串
     * @param str1 第一个字符串
     * @param str2 第二个字符串
     * @param operator 比较运算符（可以是中文或英文）
     * @return 比较结果
     * @throws IllegalArgumentException 如果运算符无效或类型转换错误
     */
    public  boolean compare(String str1, String str2, String operator) throws IllegalArgumentException {

        if (OPERATOR_MAP.contains(operator) == false) {
            throw new IllegalArgumentException("错误：不支持的运算符 '" + operator + "'！");
        }

        if (operator.equals("==")) { //这个符合特殊，既可以 比较数字也可以比较字符串
            if (NumberUtil.isNumber(str2) == false) { //如果比较值不是数字，那就按字符串进行比较
                return Objects.equals(str1, str2);
            }
        }



        // 根据运算符类型执行适当的比较
        if (isNumericOperator(operator)) {
            return compareNumeric(str1, str2, operator);
        }
        else if (isStringOperator(operator)) {
            return compareString(str1, str2, operator);
        }
        else {
            throw new IllegalArgumentException("错误：不支持的运算符 '" + operator + "'！");
        }
    }
    /**
     * 检查是否为数值运算符
     */
    private static boolean isNumericOperator(String operator) {
        return "==".equals(operator) || "!=".equals(operator) ||
                ">".equals(operator) || "<".equals(operator) ||
                ">=".equals(operator) || "<=".equals(operator);
    }

    /**
     * 检查是否为字符串运算符
     */
    private static boolean isStringOperator(String operator) {
        return "contains".equals(operator) || "notcontains".equals(operator) ||
                "startsWith".equals(operator) || "endsWith".equals(operator);
    }

    /**
     * 将两个字符串作为数值进行比较
     * @param str1 要转换为数字的第一个字符串
     * @param str2 要转换为数字的第二个字符串
     * @param operator 数值比较运算符
     * @return 数值比较的布尔结果
     * @throws IllegalArgumentException 如果字符串无法转换为数字
     */
    private static boolean compareNumeric(String str1, String str2, String operator) {
        Double num1, num2;

        // 尝试将第一个字符串转换为数字
        try {
            num1 = Double.parseDouble(str1.trim());
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("错误：无法将 '" + str1 + "' 转换为数值！");
        }

        // 尝试将第二个字符串转换为数字
        try {
            num2 = Double.parseDouble(str2.trim());
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("错误：无法将 '" + str2 + "' 转换为数值！");
        }

        // 根据指定的运算符执行比较
        switch (operator) {
            case "==":
                // 对于等式检查，我们需要考虑整数比较以避免浮点精度问题
                if (isInteger(str1) && isInteger(str2)) {
                    return Long.parseLong(str1.trim()) == Long.parseLong(str2.trim());
                }
                return Math.abs(num1 - num2) < 1e-10; // 使用epsilon进行双精度比较
            case "!=":
                if (isInteger(str1) && isInteger(str2)) {
                    return Long.parseLong(str1.trim()) != Long.parseLong(str2.trim());
                }
                return Math.abs(num1 - num2) >= 1e-10;
            case ">": return num1 > num2;
            case "<": return num1 < num2;
            case ">=": return num1 >= num2;
            case "<=": return num1 <= num2;
            default:
                throw new IllegalArgumentException("错误：不支持的数值运算符 '" + operator + "'！");
        }
    }

    /**
     * 检查字符串是否表示整数值
     */
    private static boolean isInteger(String str) {
        str = str.trim();
        try {
            Long.parseLong(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 使用字符串运算符比较两个字符串
     * @param str1 第一个字符串
     * @param str2 第二个字符串
     * @param operator 字符串比较运算符
     * @return 字符串比较的布尔结果
     * @throws IllegalArgumentException 如果提供了无效的字符串运算符
     */
    private static boolean compareString(String str1, String str2, String operator) {
        switch (operator) {
            case "contains": return str1.contains(str2);
            case "notcontains": return !str1.contains(str2);
            case "startsWith": return str1.startsWith(str2);
            case "endsWith": return str1.endsWith(str2);
            default:
                throw new IllegalArgumentException("错误：不支持的字符串运算符 '" + operator + "'！");
        }
    }

}
